// Include standard headers
#include "Utils.h"

// Include GLEW
#include <GL/glew.h>

// Include GLFW
#include <GL/glfw.h>

#include "states/State.h"
#include "states/StateEndless.h"
#include "renderer/GameRenderer.h"

using namespace VectorTD;

std::list<Updatable*> m_updateObjects;

void InsertUpdatable(Updatable* p_updatable)
{
	m_updateObjects.push_back(p_updatable);
}

int main(void)
{
	std::srand(static_cast<unsigned int>(time(NULL)));

	State* g_CurrentState;
	g_CurrentState = new StateEndless();

	InsertUpdatable(g_CurrentState);

	// Initialise GLFW
	if(!glfwInit())
	{
		fprintf( stderr, "Failed to initialize GLFW\n" );
		return -1;
	}

	glfwOpenWindowHint(GLFW_FSAA_SAMPLES, 4);
	glfwOpenWindowHint(GLFW_OPENGL_VERSION_MAJOR, 3);
	glfwOpenWindowHint(GLFW_OPENGL_VERSION_MINOR, 3);
	glfwOpenWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

	// Open a window and create its OpenGL context
	if( !glfwOpenWindow( 1024, 768, 0,0,0,0, 32,0, GLFW_WINDOW ) )
	{
		fprintf( stderr, "Failed to open GLFW window. If you have an Intel GPU, they are not 3.3 compatible. Try the 2.1 version of the tutorials.\n" );
		glfwTerminate();
		return -1;
	}

	glewExperimental = GL_TRUE;
	// Initialize GLEW
	if (glewInit() != GLEW_OK)
	{
		fprintf(stderr, "Failed to initialize GLEW\n");
		return -1;
	}

	glfwSetWindowTitle("VectorTD");

	// Ensure we can capture the escape key being pressed below
	glfwEnable(GLFW_STICKY_KEYS);
	glfwEnable(GLFW_STICKY_MOUSE_BUTTONS);

	// Dark blue background
	glClearColor(0.0f, 0.0f, 0.4f, 0.0f);

	GLuint VertexArrayID;
    glGenVertexArrays(1, &VertexArrayID);
    glBindVertexArray(VertexArrayID);

	double lastTime = glfwGetTime();
	double currentTime = 0;
	double deltaTime = 0;
	GameRenderer& gr = GameRenderer::GetInstance();

	do
	{
		currentTime = glfwGetTime()*1000.0f;
		deltaTime = currentTime - lastTime; 
		lastTime = currentTime;

		//int glfwGetMouseButton(GLFW_MOUSE_BUTTON_LEFT)
		//void glfwGetMousePos( int *x, int *y )

		for(std::list<Updatable* >::iterator it = m_updateObjects.begin() ; it != m_updateObjects.end() ; )
		{
			if(!(*it)->Update(deltaTime))
				it = m_updateObjects.erase(it);
			else
				it++;
		}

		// Clear the screen
		glClear(GL_COLOR_BUFFER_BIT);

		gr.Render(deltaTime);

		// Swap buffers
		glfwSwapBuffers();

	} // Check if the ESC key was pressed or the window was closed
	while( glfwGetKey( GLFW_KEY_ESC ) != GLFW_PRESS &&
		   glfwGetWindowParam(GLFW_OPENED));

	// Close OpenGL window and terminate GLFW
	glfwTerminate();

	return 0;
}

